/**
 * Copyright 厦门中软海晟信息技术有限公司 版权所有 违者必究 2019
 */
package com.opencvjava.practise;

import com.opencvjava.lessons.core.L8_DiscreteFourierTransform;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.LinkedList;

import static com.opencvjava.support.util.CvUtils.imshow;
import static com.opencvjava.support.util.CvUtils.mat;
import static org.opencv.imgcodecs.Imgcodecs.IMREAD_GRAYSCALE;
import static org.opencv.imgproc.Imgproc.CV_SHAPE_RECT;
import static org.opencv.imgproc.Imgproc.MORPH_CLOSE;
import static org.opencv.imgproc.Imgproc.MORPH_OPEN;
import static org.opencv.imgproc.Imgproc.MORPH_TOPHAT;
import static org.opencv.imgproc.Imgproc.THRESH_BINARY;
import static org.opencv.imgproc.Imgproc.getStructuringElement;
import static org.opencv.imgproc.Imgproc.morphologyEx;
import static org.opencv.imgproc.Imgproc.threshold;

/**
 * @author : sunzb
 * @date: 2019/8/16
 */
@Service
public class Txm {

    @Autowired
    L8_DiscreteFourierTransform l8_discreteFourierTransform;

    private int kernelSize = 7;
    public void test() {
        Mat gray = mat("txm.png", IMREAD_GRAYSCALE);
        Mat binary = new Mat();
        threshold(gray, binary, 127, 255, THRESH_BINARY);
        int total = (int) binary.total();
        int rows = binary.rows();
        int cols = binary.cols();
        byte[] biData = new byte[total];
        binary.get(0, 0, biData);
        imshow("阈值二值化", binary);
        Mat element = getStructuringElement(CV_SHAPE_RECT,
                new Size(2 * kernelSize + 1, 2 * kernelSize + 1),
                new Point(kernelSize, kernelSize));
        Mat hat = new Mat();
        morphologyEx(binary, hat, MORPH_TOPHAT, element);
        kernelSize = 5;
        element = getStructuringElement(CV_SHAPE_RECT,
                new Size(2 * kernelSize + 1, 2 * kernelSize + 1),
                new Point(kernelSize, kernelSize));
        morphologyEx(hat, hat, MORPH_OPEN, element);
        byte[] hatData = new byte[total];
        hat.get(0, 0, hatData);
        imshow("顶帽再开", hat);
        Mat dst = new Mat(hat.size(), hat.type());
        byte[] dstData = new byte[total];
        int left = Integer.MAX_VALUE, right = 0, top = Integer.MAX_VALUE, bottom = 0;
        int color;
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                color = hatData[row * cols + col];
                if (color != 0) {
                    if (row < top) top = row;
                    if (row > bottom) bottom = row;
                    if (col < left) left = col;
                    if (col > right) right = col;
                }
            }
        }
        int index;
        for (int i = 0; i < total; i++) {
            dstData[i] = -1;
        }
        outer:
        for (int row = top - 50; row < bottom - 10; row++) {
            for (int col = left; col < right; col++) {
                bfs(row, col, rows, cols, biData, dstData);
//                dstData[row * cols + col] = biData[row * cols + col];
            }
        }
        dst.put(0, 0, dstData);
        imshow("结果", dst);
        l8_discreteFourierTransform.dftTest(dst);
    }

    private void bfs(int row, int col, int rows, int cols, byte[] biData, byte[] dstData) {
        LinkedList<String> bfs = new LinkedList<>();
        int curRow = row, curCol = col;
        if (biData[curRow * cols + curCol] == 0)
            bfs.push(curRow + "," + curCol);
        while (!bfs.isEmpty()) {
            String[] point = StringUtils.split(bfs.pop(), ",");
            curRow = Integer.parseInt(point[0]);
            curCol = Integer.parseInt(point[1]);
//            System.out.println("bfs.size():" + bfs.size());
            int index = curRow * cols + curCol;
            dstData[index] = 0;
            biData[index] = -1;
            if (curRow - 1 >= 0 && curCol - 1 >= 0) {
                int tlIndex = (curRow - 1) * cols + curCol - 1;
                if (biData[tlIndex] == 0)
                    bfs.push((curRow - 1) + "," + (curCol - 1));
            }
            if (curRow - 1 >= 0) {
                int topIndex = (curRow - 1) * cols + curCol;
                if (biData[topIndex] == 0)
                    bfs.push((curRow - 1) + "," + curCol);
            }
            if (curRow - 1 >= 0 && curCol + 1 < cols) {
                int trIndex = (curRow - 1) * cols + curCol + 1;
                if (biData[trIndex] == 0)
                    bfs.push((curRow - 1) + "," + (curCol + 1));
            }
            if (curCol - 1 >= 0) {
                int leftIndex = curRow * cols + curCol - 1;
                if (biData[leftIndex] == 0)
                    bfs.push(curRow + "," + (curCol - 1));
            }
            if (curCol + 1 < cols) {
                int rightIndex = curRow * cols + curCol + 1;
                if (biData[rightIndex] == 0)
                    bfs.push(curRow + "," + (curCol + 1));
            }
            if (curRow + 1 < rows && curCol - 1 >= 0) {
                int blIndex = (curRow + 1) * cols + curCol - 1;
                if (biData[blIndex] == 0)
                    bfs.push((curRow + 1) + "," + (curCol - 1));
            }
            if (curRow + 1 < rows) {
                int bottomIndex = (curRow + 1) * cols + curCol;
                if (biData[bottomIndex] == 0)
                    bfs.push((curRow + 1) + "," + curCol);
            }
            if (curRow + 1 < rows && curCol + 1 < cols) {
                int brIndex = (curRow + 1) * cols + curCol + 1;
                if (biData[brIndex] == 0)
                    bfs.push((curRow + 1) + "," + (curCol + 1));
            }
        }
    }

    private void dg(int row, int col, int cols, byte[] biData, byte[] dstData) {
        int index = row * cols + col;
        if (biData[index] == 0) dstData[index] = 0;
        else return;
        dg(row - 1, col - 1, cols, biData, dstData);
        dg(row - 1, col, cols, biData, dstData);
        dg(row - 1, col + 1, cols, biData, dstData);
        dg(row, col - 1, cols, biData, dstData);
        dg(row, col + 1, cols, biData, dstData);
        dg(row + 1, col - 1, cols, biData, dstData);
        dg(row + 1, col, cols, biData, dstData);
        dg(row + 1, col + 1, cols, biData, dstData);
    }
}
